home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / find / dist / lib / strtol.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-05-14  |  3.8 KB  |  174 lines

  1. /* Copyright (C) 1991, 1992 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3.  
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Library General Public License as
  6. published by the Free Software Foundation; either version 2 of the
  7. License, or (at your option) any later version.
  8.  
  9. The GNU C Library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12. Library General Public License for more details.
  13.  
  14. You should have received a copy of the GNU Library General Public
  15. License along with the GNU C Library; see the file COPYING.LIB.  If
  16. not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  17. Cambridge, MA 02139, USA.  */
  18.  
  19. #include <ctype.h>
  20. #include <errno.h>
  21.  
  22. #if HAVE_LIMITS_H
  23. #include <limits.h>
  24. #else
  25. #define    LONG_MAX (~(1 << (sizeof (long) * 8 - 1)))
  26. #define LONG_MIN (-LONG_MAX-1)
  27. #define ULONG_MAX ((unsigned long) ~(unsigned long) 0)
  28. #endif
  29.  
  30. #if STDC_HEADERS
  31. #include <stddef.h>
  32. #include <stdlib.h>
  33. #else
  34. #define NULL 0
  35. extern int errno;
  36. #endif
  37.  
  38. #ifndef    UNSIGNED
  39. #define    UNSIGNED    0
  40. #endif
  41.  
  42. /* Convert NPTR to an `unsigned long int' or `long int' in base BASE.
  43.    If BASE is 0 the base is determined by the presence of a leading
  44.    zero, indicating octal or a leading "0x" or "0X", indicating hexadecimal.
  45.    If BASE is < 2 or > 36, it is reset to 10.
  46.    If ENDPTR is not NULL, a pointer to the character after the last
  47.    one converted is stored in *ENDPTR.  */
  48. #if    UNSIGNED
  49. unsigned long int
  50. #define    strtol    strtoul
  51. #else
  52. long int
  53. #endif
  54. strtol (nptr, endptr, base)
  55.      char *nptr;
  56.      char **endptr;
  57.      int base;
  58. {
  59.   char sign;
  60.   register unsigned long int cutoff;
  61.   register unsigned int cutlim;
  62.   register unsigned long int i;
  63.   register char *s;
  64.   register unsigned char c;
  65.   char *save;
  66.   int overflow;
  67.  
  68.   if (base < 0 || base == 1 || base > 36)
  69.     base = 10;
  70.  
  71.   s = nptr;
  72.  
  73.   /* Skip white space.  */
  74.   while (isspace (*s))
  75.     ++s;
  76.   if (*s == '\0')
  77.     goto noconv;
  78.  
  79.   /* Check for a sign.  */
  80.   if (*s == '-')
  81.     {
  82.       sign = -1;
  83.       ++s;
  84.     }
  85.   else if (*s == '+')
  86.     {
  87.       sign = 1;
  88.       ++s;
  89.     }
  90.   else
  91.     sign = 1;
  92.  
  93.   if (base == 16 && s[0] == '0' && toupper (s[1]) == 'X')
  94.     s += 2;
  95.  
  96.   /* If BASE is zero, figure it out ourselves.  */
  97.   if (base == 0)
  98.     if (*s == '0')
  99.       {
  100.     if (toupper (s[1]) == 'X')
  101.       {
  102.         s += 2;
  103.         base = 16;
  104.       }
  105.     else
  106.       base = 8;
  107.       }
  108.     else
  109.       base = 10;
  110.  
  111.   /* Save the pointer so we can check later if anything happened.  */
  112.   save = s;
  113.  
  114.   cutoff = ULONG_MAX / (unsigned long int) base;
  115.   cutlim = ULONG_MAX % (unsigned long int) base;
  116.  
  117.   overflow = 0;
  118.   i = 0;
  119.   for (c = *s; c != '\0'; c = *++s)
  120.     {
  121.       if (isdigit (c))
  122.     c -= '0';
  123.       else if (isalpha (c))
  124.     c = toupper (c) - 'A' + 10;
  125.       else
  126.     break;
  127.       if (c >= base)
  128.     break;
  129.       /* Check for overflow.  */
  130.       if (i > cutoff || (i == cutoff && c > cutlim))
  131.     overflow = 1;
  132.       else
  133.     {
  134.       i *= (unsigned long int) base;
  135.       i += c;
  136.     }
  137.     }
  138.  
  139.   /* Check if anything actually happened.  */
  140.   if (s == save)
  141.     goto noconv;
  142.  
  143.   /* Store in ENDPTR the address of one character
  144.      past the last character we converted.  */
  145.   if (endptr != NULL)
  146.     *endptr = (char *) s;
  147.  
  148. #if    !UNSIGNED
  149.   /* Check for a value that is within the range of
  150.      `unsigned long int', but outside the range of `long int'.  */
  151.   if (i > (unsigned long int) (sign > 0 ? LONG_MAX : - LONG_MIN))
  152.     overflow = 1;
  153. #endif
  154.  
  155.   if (overflow)
  156.     {
  157.       errno = ERANGE;
  158. #if    UNSIGNED
  159.       return ULONG_MAX;
  160. #else
  161.       return sign > 0 ? LONG_MAX : LONG_MIN;
  162. #endif
  163.     }
  164.  
  165.   /* Return the result of the appropriate sign.  */
  166.   return i * sign;
  167.  
  168. noconv:;
  169.   /* There was no number to convert.  */
  170.   if (endptr != NULL)
  171.     *endptr = (char *) nptr;
  172.   return 0L;
  173. }
  174.